											library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity controller is

port(
	clock: in std_logic; 

	--what the formula gave back after the last assignment
	satisfied: in std_logic;		   
	
	--no more assignments left so stop going
	exhausted: in std_logic;
	
	reset: in std_logic;
	enable: in std_logic;
	
	f_enable: out std_logic;
	f_reset: out std_logic;
	o_enable: out std_logic;
	a_enable: out std_logic;
	a_reset: out std_logic
	
);
end entity controller;

architecture controller_behavior of controller is
--define enumerated states
type State is(Res, Formula, Assignment, Output);

--declare state signals
signal next_state: State := Res;
signal current_state: State := Res;

--internal signals, used to represent output signals (can't change output signals directly)
signal f_temp: std_logic;
signal f_res: std_logic;
signal o_temp: std_logic;
signal a_temp: std_logic;
signal a_res: std_logic;

begin

--state switching process
process(clock, enable)

begin --process		
	--asynchronous reset		
	if reset = '1' then
		current_state <= Res;
	
	elsif rising_edge(clock) and enable= '1' then
		current_state <= next_state;
		
	end if;
end process;

process(clock, reset, satisfied, exhausted, enable, current_state)

begin -- process

case current_state is
	
	when Res =>
		a_temp <= '0';
		a_res <= '1';
		o_temp <= '0';
		f_temp <= '0';
		f_res <= '1';
	
		if enable = '1' and reset='0' then
			next_state <= Formula;

		else
			next_state <= Res;
			
		end if;
	
	when Formula =>
	
		a_temp <= '0';
		a_res <= '0';
		o_temp <= '0';
		f_temp <= '1';
		f_res <= '0';
		
		if satisfied = '1' or exhausted = '1' then
		
			next_state <= Output;
			
		else

			
			next_state <= Assignment;
			
		end if;	
		
	when Assignment =>	 
	
		a_temp <= '1';
		a_res <= '0';
		o_temp <= '0';
		f_temp <= '0';
		f_res <= '0';

		next_state <= Formula;
		
	when Output =>

		a_temp <= '0';
		a_res <= '0';
		o_temp <= '1';
		f_temp <= '0';
		f_res <= '0';
		
		next_state <= Output;
		
end case;		

end process;

--output driving process
process(f_temp, f_res, a_temp, a_res, o_temp)

begin --process
	
f_enable <= f_temp;
f_reset <= f_res;
o_enable <= o_temp; 
a_enable <= a_temp;
a_reset <= a_res;

end process;
		
end architecture controller_behavior;			